<template lang="pug">
div.bctree-wrap
    el-input(
        placeholder="输入关键字进行过滤"
        v-model="filterText"
        size="small"
        :clearable="true"
        v-if="filter"
        )
    .tree-inner
        el-tree(
            :data="treeData"
            :show-checkbox="showCheckbox"
            :empty-text="emptyText"
            ref="treeRef"
            :lazy="lazy"
            :load="loadNode"
            :node-key="nodeKey"
            highlight-current
            :check-strictly="checkStrictly"
            :default-expand-all="defaultExpandAll"
            :expand-on-click-node="false"
            :filter-node-method="filterNode"
            :props="defaultPropsCopy"
            :default-checked-keys="defaultCheckedKeys"
            :default-expanded-keys="defaultExpandedKeysCopy"
            @node-click="nodeClick"
            @node-contextmenu="nodeContextmenu"
            @check-change="checkChange"
            @check="check"
            )
            template(#default="{ node, data }")
                span.custom-tree-node
                    .label-wrap
                        img.iconImg(v-if="data.imgIcon" :src="data.imgIcon")
                        template(v-else-if="data.fontIcon")
                            i(:class="data.fontIcon")
                        template(v-else-if="imgIcon && imgIcon.length > 0")
                            img.iconImg(v-if="node.childNodes.length || (lazy && data[defaultProps.isParent])" :class="imgIcon[0]")
                            img.iconImg(v-else :class="imgIcon[1]")
                        el-icon(v-else-if="data[defaultPropsCopy.parentId]==rootId||(data[defaultPropsCopy.children]&&data[defaultPropsCopy.children].length>0)||data.isfolder" :size="16" style="margin-right: 5px;color:#ff9800;")
                            FolderOpened(v-if="node.expanded")
                            Folder(v-else)
                        el-icon(v-else :size="16"  style="margin-right: 5px;")
                            Document()
                        span(v-show="!data.edit" :style="{color:data.color == 'blue'?'#00FBFF':data.color}" tabindex="1" :data="data[defaultPropsCopy.id]" :title="data[defaultPropsCopy.label]") {{ data[defaultPropsCopy.label] }}
                        input(v-show="data.edit" v-model="data[defaultPropsCopy.label]" :id='data[defaultPropsCopy.id]' @blur="nameEdit(data)")
                        span(v-show="data.fileNum && data.fileNum > 0" class="fileNumSpan" :id="'_'+data[defaultPropsCopy.id]") {{ data.fileNum }}
                        span(v-if="data.requireFlag=='1'&&!data[defaultPropsCopy.children]" style="color:red;margin:0 2px;") *
                    i.el-icon-map-location(v-show="data.maplocation" @click.stop="mapLocation(data)" title="经纬度")
                    //- i.diyIcon(v-show="data.diyIcon" :class="data.diyIcon" @click.stop="diyIcionClick(data)" :title="data.diyIconTitle")
                    el-button(link type="primary" @click.stop="diyIcionClick(data)"
                        v-show="data.diyIcon"
                        :title="data.diyIconTitle"
                        :icon="data.diyIcon == 'Refresh'?Refresh:''"
                    )
                    .label-wrap.tool-wrap(:style="{visibility:toolLight?'inherit':'hidden'}" v-if="toolShow")
                        el-button(link type="primary" @click.stop="append(node,data)"
                            v-if="data.addShow && peCopy.add === true "
                            title="新增"
                            :icon="DocumentAdd"
                        )
                        el-button(link type="primary" @click.stop="edit(data)"
                            v-if="data.editShow && peCopy.edit === true "
                            title="修改"
                            :icon="Edit"
                        )
                        el-button(link type="primary" @click.stop="remove(node, data)"
                            v-if="data.delShow && peCopy.del === true "
                            title="删除"
                            :icon="Delete"
                        )
</template>
<script setup>
import { DocumentAdd, Edit, Delete } from '@element-plus/icons-vue'
import { createHash, storageGet } from '@/utils'
import { success, deleteConfirm, warning, confirm } from '@/utils/message'
import { ref, onMounted, watch } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
const props = defineProps({
    nodeKey: {
        type: String,
        default: 'id'
    },
    location: { //定位图标
        type: Boolean,
        default: false
    },
    lazy: { //懒加载
        type: Boolean,
        default: false
    },
    load: {
        type: Function,
        default: function(){

        }
    },
    showCheckbox: { //复选框的显隐
        type: Boolean,
        default: false
    },
    checkboxConnect: { //复选框的显隐 关联，单选关联复选框
        type: Boolean,
        default: false
    },
    firstFloor: { //是否默认打开一级目录
        type: Boolean,
        default: true
    },
    editType: { //name只修改名字 diy自定义 抛出点击事件
        type: String,
        default: 'diy'
    },
    filter: { //过滤
        type: Boolean,
        default: false
    },
    labelText: { //文本
        type: String,
        default: ''
    },
    checkStrictly: { //多选框是否与父级强关联，默认false关联
        type: Boolean,
        default: false
    },
    removeBefore: { //是否只抛出删除事件
        type: Boolean,
        default: true
    },
    toolShow: { //是否需要工具条
        type: Boolean,
        default: true
    },
    toolLight: { //工具条是否常亮 默认false不常亮，hover或者选中常亮
        type: Boolean,
        default: false
    },
    imgIcon: { //父子自定义icon
        type: Array,
        default: function(){
            return []
        }
    },
    fontIcon: { //父子自定义icon
        type: Array,
        default: function(){
            return []
        }
    },
    data: {
        type: Array,
        default: function(){
            return []
        }
    },
    defaultProps: {
        type: Object,
        default: function(){
            return {}
        }
    },
    rootId: { //根节点id
        type: String,
        default: '-1'
    },
    defaultCheckedKeys: { //默认勾选的节点
        type: Array,
        default: function(){
            return []
        }
    },
    defaultExpandedKeys: { // 默认展开的节点
        type: Array,
        default: function(){
            return []
        }
    },
    defaultExpandAll: { // 默认是否全部展开
        type: Boolean,
        default: false
    },
    ititle: { //第一个图标解释
        type: String,
        default: '新增'
    },
    emptyText: { //
        type: String,
        default: '暂无数据'
    }
})
const defaultPropsCopy = ref({
    children: 'children',
    label: 'name',
    id: 'id',
    parentId: 'parentId'
})
watch(()=>props.defaultProps, (newData)=>{
    defaultPropsCopy.value = {
        ...defaultPropsCopy.value,
        ...newData
    }
}, { immediate: true })
const refId = ref(createHash())
const treeData = ref([])
const filterText = ref('')

const selectedList = ref([])

const defaultExpandedKeysCopy = ref([])
watch(()=>props.defaultExpandedKeys, ()=>{
    defaultExpandedKeysCopy.value = props.defaultExpandedKeys.value
})

const peCopy = ref({
    add: true,
    edit: true,
    del: true
})
watch(()=>props.pe, ()=>{
    peCopy.value = props.pe.value
    const permission = storageGet('permission') || {}
    peCopy.value.add = permission[props.pe.add]
    peCopy.value.edit = permission[props.pe.edit]
    peCopy.value.del = permission[props.pe.del]
})

// watch(()=>defaultPropsCopy.value, (val)=>{
//     if (props.lazy && !val.isLeaf){
//         this.$set(val, 'isLeaf', 'isLeaf')
//     }
// }, { immediate: true })
const treeRef = ref()
let isDfault = false
watch(()=>props.defaultCheckedKeys, (val)=>{
    if(val && val.length > 0){
        isDfault = true
    }
    treeRef.value.setCheckedKeys(val)
})
watch(()=>props.labelText, (val)=>{
    treeRef.value.filter(val)
})
watch(()=>props.data, (datas)=>{
    if (datas && datas.length > 0){
        if(datas[0][defaultPropsCopy.value.children]){
            treeData.value = datas
        }else{
            let midData = {}
            let midArr = []
            datas.forEach(val => {
                midData[val[defaultPropsCopy.value.id]] = val
            })
            datas.forEach(val => {
                if(midData[val[defaultPropsCopy.value.parentId]]){
                    midData[val[defaultPropsCopy.value.parentId]].children = midData[val[defaultPropsCopy.value.parentId]].children || []
                    midData[val[defaultPropsCopy.value.parentId]].children.push(val)
                }
                if(val[defaultPropsCopy.value.parentId] == props.rootId){
                    midArr.push(val)
                }
            })
            treeData.value = midArr
        }
        if (props.firstFloor){
            firstFloorInit(treeData.value)
        }
    } else {//清空
        treeData.value = []
    }
}, { immediate: true })
const emit = defineEmits(['diyclick', 'maplocation', 'nameEdit', 'nodeClick', 'nodeContextmenu', 'checkChange', 'check', 'append', 'edit', 'remove'])
const diyIcionClick = (item)=>{//自定义按钮点击
    emit('diyclick', item)
}
const mapLocation = (data)=>{
    emit('maplocation', data)
}
const loadNode = (node, resolve)=>{//懒加载预处理
    load(node, data => {
        dataInit(data)
        resolve(data)
    })
}
const getAllNode = ()=>{
    const arr = []
    function run(data){
        data.forEach(val => {
            arr.push(val)
            if (val[defaultPropsCopy.value.children] && val[defaultPropsCopy.value.children].length > 0){
                run(val[defaultPropsCopy.value.children])
            }
        })
    }
    run(treeData.value)
    return arr
}
const getCheckedNodes = () =>{//获取选中节点
    return treeRef.value.getCheckedNodes()
}

const getCurrentNode = () =>{
    return treeRef.value.getCurrentNode()
}

const getNode = (val) =>{//获取信息
    return treeRef.value.getNode(val)
}

const nameEdit = (data)=>{//名字修改失去焦点
    data.edit = false
    emit('nameEdit', data)
}

const firstFloorInit = (data)=>{//默认打开以及目录
    defaultExpandedKeysCopy.value = []
    data.forEach(val => {
        if (!defaultExpandedKeysCopy.value.includes(val[defaultPropsCopy.value.id])){
            defaultExpandedKeysCopy.value.push(val[defaultPropsCopy.value.id])
        }
    })
}

const setChecked = (data, checked) =>{//设置节点选中状态
    treeRef.value.setChecked(data, checked)
}

const dataInit = (data)=>{
    data.forEach(val => {
        val.id = val[defaultPropsCopy.value.id]
        val.isLeaf = val[defaultPropsCopy.value.isParent] !== true
        val.edit = false
        if (val[defaultPropsCopy.value.parentId] == props.rootId || val[defaultPropsCopy.value.parentId] === null){
            val.delShow = val.parentDel || false// 显示删除
        } else {
            val.delShow = val.delShow || false// 显示删除
        }
        val.editShow = val.editShow !== false//显示修改
        val.addShow = val.addShow !== false//显示修改
        if (val[defaultPropsCopy.value.children] && val[defaultPropsCopy.value.children].length > 0){
            dataInit(val[defaultPropsCopy.value.children])
        }
    })
}

const nodeClick = (data, node, component)=>{//节点点击事件
    document.body.click()//tree结构阻止事件传递，导致右上角工程打开后没有关闭
    const midData = data
    midData.parent = node.parent
    emit('nodeClick', midData, node, component)
    if (props.showCheckbox && props.checkboxConnect){
        setChecked(data, true)
    }
}

const nodeContextmenu = (event, data, node, component)=>{//节点右键点击事件
    emit('nodeContextmenu', event, data, node, component)
}
let timer = ''
const checkChange = (data, checked)=>{// 复选框选中是触发data, checked, childrenChecked
    selectedList.value.push(data)
    if (timer){
        clearTimeout(timer)
    }
    timer = setTimeout(()=>{
        emit('checkChange', [...selectedList.value], checked, isDfault)
        isDfault = false
        selectedList.value = []
    }, 10)
}

const check = (data, checkedData)=>{//选中事件
    setTimeout(()=>{
        emit('check', data, checkedData)
    }, 10)
}

const setCurrentKey = (key)=>{//设置某个节点被选中
    treeRef.value.setCurrentKey(key)
    // $(`[data=${key}]`)[0] && $(`[data=${key}]`)[0].focus()
}

const filterNode = (value, data)=>{
    if (!value){
        return true
    }
    if (data[defaultPropsCopy.value.label]){
        return data[defaultPropsCopy.value.label].indexOf(value) !== props.rootId
    }
}
let optionNode = {}
const append = (node, data)=>{//新增事件
    optionNode = node
    emit('append', data)
}

const appendSuccess = (data)=>{//新增成功回调
    dataInit([data])
    treeRef.value.append(data, optionNode)
}

let optionItem = {}
const edit = (data)=>{
    optionItem = data
    if (props.editType == 'name' && props.toolShow){
        data.edit = true
        setTimeout(()=>{
            document.getElementById(data[defaultPropsCopy.value.id]).focus()
        }, 50)
    } else {
        emit('edit', data)
    }

}

const remove = (node, data)=>{//删除事件
    if (props.removeBefore){//只抛出事件
        emit('remove', data)
        return
    }
}

defineExpose({
    treeData,
    setCurrentKey,
    setChecked,
    getCurrentNode,
    getNode
})
</script>
<style lang="less" scoped>
.bctree-wrap{
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    .tree-inner{
        flex-grow: 1;
        overflow: auto;
    }
}
.label-wrap{
    display: flex;
    align-items: center;
    margin-right: 5px;
    font-size: 16px;
    :last-child{
        margin-right: 0;
    }
    .iconImg{
        width: 16px;
        margin-right: 4px;
    }
    i {
        margin-right:4px;
        font-size: 22px;
    }
    input{
        border-bottom: 1px solid #eee;
        width: 100%;
        min-width: 100px;

    }
    &>span{
        text-overflow: ellipsis;
        overflow: hidden;
        white-space: nowrap;
    }
}
  .custom-tree-node {
    // max-width: 90%;
    flex: 1;
    display: flex;
    align-items: center;
    font-size: 14px;
    padding-right: 8px;
    &:hover .tool-wrap{
        visibility: inherit !important;
    }
  }
  .tool-wrap{
      i:hover{
          color: #008cff;
      }
  }
 :deep(.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content){
    //   background:#ffd393 !important;
    background: transparent !important;
    .label-wrap span{
        color: #f59f22;
        font-weight: bold;
    }
  }
  :deep(.el-tree-node__content){
      height: 26px !important;
  }
  .folder-color{
      color:#ff9900
  }
  .doc-color{
      color:#666
  }
  :deep(.el-checkbox__input.is-disabled .el-checkbox__inner){
      background-color: #d1d1d1;
  }
  :deep(.fileNumSpan){
      color: white;
      background-color: red;
      font-size: 12px;
      border-radius: 10px;
      width: auto;
      min-width: 16px;
      text-align: center;
      margin-left: 5px;
      line-height: 16px;
  }
  .el-icon-map-location{
      font-size: 16px;
      color: #fff;
      margin-left: 5px;
  }
  .red{
      color: red;
      margin: 5px 2px 0 0;
  }
  .diyIcon{
    font-size: 18px;
    margin: 0 5px;
    &:hover{
        color: #008cff;
    }
  }
:deep(.el-button+.el-button){
    margin-left: 5px;
}
</style>
<style>
.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content .custom-tree-node span{
    color: #ff9800;
    font-weight: bold;
}
.el-tree-node>.el-tree-node__children{
    overflow: inherit !important;
  }
  .el-tree-node>.el-tree-node__children.el-collapse-transition-enter-active, .el-tree-node>.el-tree-node__children.el-collapse-transition-leave-active{
    overflow: hidden !important;
}
</style>